using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Media;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.Utility;

namespace SCSFContrib.CompositeUI.WPF.Workspaces
{
	/// <summary>
	/// Provides information to the <see cref="WindowWorkspace"/> when displaying smart parts.
	/// </summary>
	public class WindowSmartPartInfo : SmartPartInfo
	{
		private bool _isModal;
		private double? _width;
		private double? _height;
		private double? _minWidth;
		private double? _minHeight;
		private double? _maxWidth;
		private double? _maxHeight;
		private double? _left;
		private double? _top;
		private bool? _showInTaskbar;
		private bool? _isTopmost;
		private ImageSource _icon;
		private bool _iconSet;
		private ResizeMode? _resizeMode;
		private SizeToContent? _sizeToContent;
		private WindowStartupLocation _startupLocation;
		private WindowState? _state;
		private WindowStyle? _style;
		private Style _wpfStyle;
		private bool _wpfStyleSet;
		private Window _owner;
		private bool? _dialogResult;

		/// <summary>
		/// Gets or sets a value indicating whether the <see cref="Window"/> displayed with this <c>WindowSmartPartInfo</c>
		/// should be displayed modally.
		/// </summary>
		public bool IsModal
		{
			get
			{
				return _isModal;
			}
			set
			{
				_isModal = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the width of the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? Width
		{
			get
			{
				return _width;
			}
			set
			{
				_width = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the height of the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? Height
		{
			get
			{
				return _height;
			}
			set
			{
				_height = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the minimum width of the <see cref="Window"/> displayed via this
		/// <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? MinWidth
		{
			get
			{
				return _minWidth;
			}
			set
			{
				_minWidth = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the minimum height of the <see cref="Window"/> displayed via this
		/// <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? MinHeight
		{
			get
			{
				return _minHeight;
			}
			set
			{
				_minHeight = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the maximum width of the <see cref="Window"/> displayed via this
		/// <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? MaxWidth
		{
			get
			{
				return _maxWidth;
			}
			set
			{
				_maxWidth = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the maximum height of the <see cref="Window"/> displayed via this
		/// <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? MaxHeight
		{
			get
			{
				return _maxHeight;
			}
			set
			{
				_maxHeight = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the left edge position of the <see cref="Window"/> displayed via this
		/// <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? Left
		{
			get
			{
				return _left;
			}
			set
			{
				_left = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the top edge position of the <see cref="Window"/> displayed via this
		/// <c>WindowSmartPartInfo</c>.
		/// </summary>
		public double? Top
		{
			get
			{
				return _top;
			}
			set
			{
				_top = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether the <see cref="Window"/> displayed with this <c>WindowSmartPartInfo</c>
		/// should be displayed in the taskbar.
		/// </summary>
		public bool? ShowInTaskbar
		{
			get
			{
				return _showInTaskbar;
			}
			set
			{
				_showInTaskbar = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether the <see cref="Window"/> displayed with this <c>WindowSmartPartInfo</c>
		/// should be displayed topmost in the z order.
		/// </summary>
		public bool? IsTopmost
		{
			get
			{
				return _isTopmost;
			}
			set
			{
				_isTopmost = value;
			}
		}

		/// <summary>
		/// Gets or sets the icon for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public ImageSource Icon
		{
			get
			{
				return _icon;
			}
			set
			{
				_icon = value;
				_iconSet = true;
			}
		}

		/// <summary>
		/// Gets or sets the resize mode for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public ResizeMode? ResizeMode
		{
			get
			{
				return _resizeMode;
			}
			set
			{
				_resizeMode = value;
			}
		}

		/// <summary>
		/// Gets or sets the auto-resizing behavior for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public SizeToContent? SizeToContent
		{
			get
			{
				return _sizeToContent;
			}
			set
			{
				_sizeToContent = value;
			}
		}

		/// <summary>
		/// Gets or sets the startup location for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public WindowStartupLocation StartupLocation
		{
			get
			{
				return _startupLocation;
			}
			set
			{
				_startupLocation = value;
			}
		}

		/// <summary>
		/// Gets or sets the state for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public WindowState? State
		{
			get
			{
				return _state;
			}
			set
			{
				_state = value;
			}
		}

		/// <summary>
		/// Gets or sets the style for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		/// <remarks>
		/// <para>
		/// This property is unrelated to WPF's style infrastructure. To apply a specific WPF style to a <see cref="Window"/>
		/// use the <see cref="WpfStyle"/> property.
		/// </para>
		/// </remarks>
		public WindowStyle? Style
		{
			get
			{
				return _style;
			}
			set
			{
				_style = value;
			}
		}

		/// <summary>
		/// Gets or sets the WPF style for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public Style WpfStyle
		{
			get
			{
				return _wpfStyle;
			}
			set
			{
				_wpfStyle = value;
				_wpfStyleSet = true;
			}
		}

		/// <summary>
		/// Gets or sets the owner window for the <see cref="Window"/> displayed via this <c>WindowSmartPartInfo</c>.
		/// </summary>
		public Window Owner
		{
			get
			{
				return _owner;
			}
			set
			{
				_owner = value;
			}
		}

		/// <summary>
		/// Gets or sets the result of a dialog window.
		/// </summary>
		/// <remarks>
		/// <para>
		/// This member is relevant when showing a modal window. It provides a means of obtaining the result of showing the dialog.
		/// </para>
		/// </remarks>
		public bool? DialogResult
		{
			get
			{
				return _dialogResult;
			}
			set
			{
				_dialogResult = value;
			}
		}

		/// <summary>
		/// Constructs a default instance of <c>WindowSmartPartInfo</c>.
		/// </summary>
		public WindowSmartPartInfo()
		{
			_startupLocation = WindowStartupLocation.Manual;
		}

		/// <summary>
		/// Constructs an instance of <c>WindowSmartPartInfo</c> with the specified title.
		/// </summary>
		/// <param name="title">
		/// The window title.
		/// </param>
		public WindowSmartPartInfo(string title)
			: this(title, null)
		{
		}

		/// <summary>
		/// Constructs an instance of <c>WindowSmartPartInfo</c> with the specified owning <see cref="Window"/>.
		/// </summary>
		/// <param name="title">
		/// The window title.
		/// </param>
		/// <param name="owner">
		/// The window that owns the window to be displayed via this <c>WindowSmartPartInfo</c>.
		/// </param>
		public WindowSmartPartInfo(string title, Window owner)
			: this()
		{
			Title = title;
			_owner = owner;
		}

		/// <summary>
		/// Applies the properties of this <c>WindowSmartPartInfo</c> to <paramref name="window"/>.
		/// </summary>
		/// <remarks>
		/// <para>
		/// This method should apply all relevant properties of this <c>WindowSmartPartInfo</c> to <paramref name="window"/>.
		/// Some properties, such as <see cref="IsModal"/>, cannot be applied. Such properties should be ignored.
		/// </para>
		/// </remarks>
		/// <param name="window">
		/// The <see cref="Window"/> to which properties will be applied.
		/// </param>
		internal virtual void ApplyTo(Window window)
		{
			Guard.ArgumentNotNull(window, "window");

			//optionally apply values to dependency properties (always applying would result in these values taking effect even when attempting to
			//set them via a WPF style, for example)
			OptionallyApplyValue(window, Window.TitleProperty, Title, !string.IsNullOrEmpty(Title));
			OptionallyApplyValue(window, Window.WidthProperty, _width);
			OptionallyApplyValue(window, Window.HeightProperty, _height);
			OptionallyApplyValue(window, Window.MinWidthProperty, _minWidth);
			OptionallyApplyValue(window, Window.MinHeightProperty, _minHeight);
			OptionallyApplyValue(window, Window.MaxWidthProperty, _maxWidth);
			OptionallyApplyValue(window, Window.MaxHeightProperty, _maxHeight);
			OptionallyApplyValue(window, Window.LeftProperty, _left);
			OptionallyApplyValue(window, Window.TopProperty, _top);
			OptionallyApplyValue(window, Window.ShowInTaskbarProperty, _showInTaskbar);
			OptionallyApplyValue(window, Window.TopmostProperty, _isTopmost);
			OptionallyApplyValue(window, Window.IconProperty, _icon, _iconSet);
			OptionallyApplyValue(window, Window.ResizeModeProperty, _resizeMode);
			OptionallyApplyValue(window, Window.SizeToContentProperty, _sizeToContent);
			OptionallyApplyValue(window, Window.WindowStateProperty, _state);
			OptionallyApplyValue(window, Window.WindowStyleProperty, _style);
			OptionallyApplyValue(window, Window.StyleProperty, _wpfStyle, _wpfStyleSet);

			//these aren't dependency properties
			window.WindowStartupLocation = _startupLocation;
			window.Owner = _owner;
		}

		/// <summary>
		/// Applies the properties of this <c>WindowSmartPartInfo</c> to <paramref name="smartPartInfo"/>.
		/// </summary>
		/// <param name="smartPartInfo">
		/// The <c>WindowSmartPartInfo</c> to be updated.
		/// </param>
		internal virtual void ApplyTo(WindowSmartPartInfo smartPartInfo)
		{
			Guard.ArgumentNotNull(smartPartInfo, "smartPartInfo");
			smartPartInfo._isModal = _isModal;
			smartPartInfo._width = _width;
			smartPartInfo._height = _height;
			smartPartInfo._minWidth = _minWidth;
			smartPartInfo._minHeight = _minHeight;
			smartPartInfo._maxWidth = _maxWidth;
			smartPartInfo._maxHeight = _maxHeight;
			smartPartInfo._left = _left;
			smartPartInfo._top = _top;
			smartPartInfo._showInTaskbar = _showInTaskbar;
			smartPartInfo._isTopmost = _isTopmost;
			smartPartInfo._icon = _icon;
			smartPartInfo._iconSet = _iconSet;
			smartPartInfo._resizeMode = _resizeMode;
			smartPartInfo._sizeToContent = _sizeToContent;
			smartPartInfo._startupLocation = _startupLocation;
			smartPartInfo._state = _state;
			smartPartInfo._style = _style;
			smartPartInfo._wpfStyle = _wpfStyle;
			smartPartInfo._wpfStyleSet = _wpfStyleSet;
			smartPartInfo._owner = _owner;
			smartPartInfo._dialogResult = _dialogResult;
		}

		private void OptionallyApplyValue<T>(DependencyObject applyTo, DependencyProperty dependencyProperty, Nullable<T> value)
			where T : struct
		{
			if (value.HasValue)
			{
				applyTo.SetValue(dependencyProperty, value.Value);
			}
		}

		private void OptionallyApplyValue<T>(DependencyObject applyTo, DependencyProperty dependencyProperty, T value, bool applyValue)
			where T : class
		{
			if (applyValue)
			{
				applyTo.SetValue(dependencyProperty, value);
			}
		}
	}
}
